package com.huan.es8.runtimefield;

import co.elastic.clients.elasticsearch._types.ScriptLanguage;
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import java.io.IOException;

/**
 * <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.6/runtime-retrieving-fields.html">官方链接</a>
 * <p>
 * 此处解决的问题： 如果将一个 text 类型的字段来进行聚合操作，
 * 即字段的 mapping 错误，如果进行修正。
 *
 * @author huan.fu
 * @date 2023/2/1 - 21:39
 */
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class RuntimeFieldCorrectMappingError extends AbstractRuntimeField {

    @Test
    @DisplayName("lineName字段是text类型，无法进行聚合操作，定义一个runtime field来进行聚合操作")
    public void test01() throws IOException {
        SearchRequest request = SearchRequest.of(searchRequest ->
                searchRequest.index(INDEX_NAME)
                        // 查询所有数据
                        .query(query -> query.matchAll(matchAll -> matchAll))
                        // runtime field字段不会出现在 _source中，需要使用使用 fields api来获取
                        .fields(fields -> fields.field("lineName"))
                        // 创建一个 runtime filed 字段类型是 keyword
                        .runtimeMappings("aggLineName", runtime ->
                                runtime
                                        // 此处给字段类型为keyword
                                        .type(RuntimeFieldType.Keyword)
                                        .script(script ->
                                        script.inline(inline ->
                                                // runtime field中如果使用 painless脚本语言，需要使用emit
                                                inline.lang(ScriptLanguage.Painless)
                                                        .source("emit(params['_source']['lineName']+'new')")
                                        )
                                )
                        )
                        // 进行聚合操作
                        .aggregations("agg_line_name", agg ->
                                // 此处的 aggLineName即为上一步runtime field的字段
                                agg.terms(terms -> terms.field("aggLineName").size(10))
                        )
                        .size(100)
        );

        System.out.println("request: " + request);
        SearchResponse<Object> response = client.search(request, Object.class);
        System.out.println("response: " + response);
    }
}
